package com.alan.camunda.boot.util;

import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.CacheLoader;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache;
import groovy.lang.Binding;
import groovy.lang.GroovyShell;
import groovy.lang.Script;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.codehaus.groovy.control.CompilationFailedException;


/**
 * 完整实际内容：
 *
 * import static  com.alan.camunda.boot.util.StringFunctions.*
 * import static  com.alan.camunda.boot.util......
 *
 * def evaluate() {
 *   return {{ my code content }}
 * }
 * return evaluate()
 *
 */
@Slf4j
public class GroovyScriptFactory {

    private static final LoadingCache<String, Class<? extends Script>> cache;
    private static final GroovyShell shell = new GroovyShell();

    private static final String scriptPrefix;
    private static final String scriptSuffix;

    static {
        String importContent = """
            import static com.alan.camunda.boot.util.StringFunctions.*
        """;

        scriptPrefix = importContent + "\n" + "def evaluate() { return ";

        scriptSuffix = """
            }
            return evaluate()
        """;

        cache = Caffeine.newBuilder()
                .maximumSize(2000)  // 设置缓存的最大容量为 2000
                .build(new CacheLoader<String, Class<? extends Script>>() {
                    @Override
                    public @Nullable Class<? extends Script> load(String key) throws Exception {
                        try {
                            if (StringUtils.isBlank(key)) {
                                throw new RuntimeException("表达式不能为空");
                            }
                            if (key.startsWith("\n")) {
                                key = key.trim();
                            }
                            String fullScript = scriptPrefix + key + scriptSuffix;
                            Script parse = shell.parse(fullScript);
                            return parse.getClass();
                        } catch (CompilationFailedException e) {
                            log.error("表达式不符合要求， 表达式为: {}", key, e);
                            throw new RuntimeException("表达式不符合要求：" + key);
                        }
                    }
                });
    }

    public static Script getScript(String script) {
        if (StringUtils.isBlank(script)) {
            throw new RuntimeException("表达式不能为空");
        }
        try {
            return cache.get(script).newInstance();
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }


    public static void main(String[] args) {
        Script script = GroovyScriptFactory.getScript("\n 1 + 2");
        script.setBinding(new Binding());
        Object result = script.run();
        System.out.println(result);
    }


}
